#include "HttpServlet.h"

#include "HttpRequest.h"
#include "HttpResponse.h"
#include "../../base/log/Logging.h"
#include "../../base/FileUtils.h"

namespace detail{
    /**
     * 默认http请求返回值
     * @param req http 请求封装
     * @param resp http 响应封装
     */
    void doDefault(const HttpRequest &req, HttpResponse *resp) {
        resp->setStatusCode(HttpResponse::k404NotFound);
        resp->addHeader("Content-Type", "application/json");
        resp->setStatusMessage("Not Found");
        resp->setStatusCode(HttpResponse::k404NotFound);
        resp->setBody("{\n"
                      "    \"timestamp\": \"" + Timestamp::now().toFormattedString(false) +"\",\n"
                      "    \"status\": 404,\n"
                      "    \"error\": \"Not Found\",\n"
                      "    \"path\": \"" + req.getPath() +"\"\n"
                      "}");
        resp->setCloseConnection(true);
    }

    const std::vector<string> CONTENT_TYPE = {"text/plain",
                                              "text/html",
                                              "application/javascript",
                                              "text/css"};

}

HttpServlet::HttpServlet(int port, int numThreads, int maxFileSize) :
        filePath_("../htmlFile"),
        maxFileSize_(maxFileSize),
        loop_(),
        server_(&loop_, InetAddress(port), "Servlet"),
        data_(),
        defaultHttpCallback_(detail::doDefault){
    server_.setHttpCallback(std::bind(&HttpServlet::doRequest, this,
                                      std::placeholders::_1, std::placeholders::_2));
    server_.setThreadNum(numThreads);
}


bool HttpServlet::hasCallback(const string &uri) {
    return data_.find(uri) != data_.end();
}


void HttpServlet::removeCallback(const std::string &uri) {
    data_.erase(uri);
    LOG_TRACE << "servlet 移除 uri 为 : " << uri << "的回调函数";
}

void HttpServlet::updateCallback(const std::string &uri, HttpServer::HttpCallback cb) {
    data_[uri] = std::move(cb);
    LOG_TRACE << "servlet 注册了 uri 为 : " << uri << "的回调函数";
}

void HttpServlet::doRequest(const HttpRequest &req, HttpResponse *resp) {
    LOG_DEBUG << "准备处理";
    const string& uri = req.getPath();
    if(hasCallback(uri)){
        // 检测回调函数是否存在, 存在回调函数直接调用回调函数处理
        data_[uri](req, resp);
        return;
    }else{
        // 进行http请求响应检查
        string fileName = filePath_ + req.getPath();
        string file;
        int err_ = FileUtils::readFile(fileName, maxFileSize_, &file, nullptr);
        if (err_ != 0) {
            // 如果读取失败就调用读取失败的处理
            defaultHttpCallback_(req, resp);
            return;
        } else {
            resp->setStatusCode(HttpResponse::k200Ok);
            HttpRequest::ContentType type = req.getFileSuffix();
            resp->addHeader("Content-Type", detail::CONTENT_TYPE[type]);
            resp->setStatusMessage("OK");
            resp->setBody(file);
            resp->setCloseConnection(true);
            return;
        }
    }
}

void HttpServlet::run() {
    LOG_INFO << "servlet running";
    server_.start();
    loop_.loop();
}